Nakama Storage Engine
すべてのアプリ、ゲームにはプロジェクト固有のデータが有る。
ユーザー向けに保存、更新、取得する。
nakama.storageテーブルに保存される。
code: .sh
select * from nakama.storage;
collection | key | user_id | value | version | read | write | create_time | update_time
-------------+-----+---------+-------+---------+------+-------+-------------+--------------
(0 rows)
Write Object
/v2/storageエンドポイントに PUT する。
code: .sh
-H "Authorization: Bearer $TOKEN" \
-d '{"objects":
[
{
"collection": "saves",
"key": "savegame",
"value": "{\"progress\": \"50\"}"
},
{
"collection": "stats",
"key": "skill",
"value": "{\"progress\": \"24\"}"
}
]
}'
code: .yml
objects:
type: array
items:
type: object
properties:
collection:
key:
value:
レスポンスはこれ
object -> acks になって帰ってくる
また、レスポンスには
collection
key
version
user_id
value が消えて version と user_id が追加される
code: .json
{
"acks": [
{
"collection": "saves",
"key": "savegame",
"version": "1e4b46c779b0142c08643164a7e808b4",
"user_id": "af250570-d999-416d-b25c-ae1ecba13001"
},
{
"collection": "stats",
"key": "skill",
"version": "be95e1fb5b403c776b39338e9cce3ce0",
"user_id": "af250570-d999-416d-b25c-ae1ecba13001"
}
]
}
Conditional writes (条件付き書き込み)
連続書き込み
書き込みレスポンスのときに返される version を使って、
書き込みリクエストにversionを含めることができる。
含めた場合、以前のバージョンと同じだった場合だけ書き込みを実行できる
(conditional write)
どういう状況で役立つか
オブジェクトを更新するとき、
fetch -> 見る -> 更新リクエスト
このとき、fetch ~ 更新リクエストまでに他のユーザーが更新していた場合、
オブジェクトは見ているときとは違う値になっている。
その場合は、書き込みを失敗させて、現在値をチェック -> 更新 とすることで
最新の情報を見て更新できる。
オークションとか、部屋の定員とか
存在しない場合書き込み
versionにglob * を指定すると、
バージョンが存在しない場合だけ書き込める
code: .sh
-H 'Authorization: Bearer <session token>' \
-d '{
"objects": [
{
"collection": "saves",
"key": "savegame",
"value": "{\"progress\": \"50\"}",
"version": "*"
}
]
}'
Read objects
POST で読み取る
collection, key, user_id をポストする
valueが返る
code: .sh
-H 'Authorization: Bearer <session token>' \
-d '{
"object_ids": [
{
"collection": "saves",
"key": "savegame",
"user_id": "some-user-id"
}
]
}'
所有者のいないオブジェクトは nullで取得できる
public オブジェクトとして使える
object_ids を複数指定すると、複数取得できる
オブジェクトには権限と所有者がいる
権限で許されている場合は、所有者でなくてもデータを見れる
List objects
code: .sh
-H 'Authorization: Bearer <session token>'
query param で取得できる
こっちはPOSTじゃなくてGET
Remove objects
PUTで消せる
(Delete出ないのは、payloadがあるから?)
code: .sh
-H 'Authorization: Bearer <session token>' \
-d '{
"object_ids": [
{
"collection": "saves",
"key": "savegame"
}
]
}'
version を指定することで、versionが一致するときだけ消せる
(条件付き削除)
code: .sh
curl -X PUT \
-H 'Authorization: Bearer <session token>' \
-d '{
"object_ids": [
{
"collection": "saves",
"key": "savegame",
"version": "<version>"
}
]
}'
Access Controle
storage engine は オブジェクトのアクセス権限を管理する2つの方法を持つ
Object ownership
Access permission
Object ownership
Storage Object は所有者とともに作成される
クライアント
システム(server side)
code runtime で作られて割り当てられた owner
クライアント or システム
システム所有の場合は、クライアントで利用するには public read access permission が必要
code: .sh
-H 'Authorization: Bearer <session token>' \
-d '{
"object_ids": [
{
"collection": "configuration",
"key": "config",
}
]
}'
code runtime は信頼できるコード(サーバーサイド)なので、
アクセス許可に関するルールから免除される。
code: .lua
local object_ids = {
{ collection = "configuration", key = "config", user_id = nil },
}
local objects = nk.storage_read(object_ids)
for _, o in ipairs(objects) do
local message = ("value: %q"):format(o.value)
nk.logger_info(message)
end
サーバーで作成するときは
明示しないとシステムが所有者になる
Object permissions
Read Permission
0: No Read
1: Owner Read
2: Public Read
Write Permission
0: No Write
1: Owner Write
クライアントから作ったときは 1, 1
サーバーで作ったときは 0, 0
がデフォルト
object に書き込むときに、
permission_write, permission_readフィールド(optional)で
intを指定して変更できる
サーバーサイドコードでもできる
nk.storage_write(table/map)